home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / lynx-2.4 / WWW / Library / Implementation / HTGroup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-28  |  17.8 KB  |  763 lines

  1.  
  2. /* MODULE                            HTGroup.c
  3. **        GROUP FILE ROUTINES
  4. **
  5. **    Contains group file parser and routines to match IP
  6. **    address templates and to find out group membership.
  7. **
  8. **
  9. ** AUTHORS:
  10. **    AL    Ari Luotonen    luotonen@dxcern.cern.ch
  11. **
  12. ** HISTORY:
  13. **
  14. **
  15. ** BUGS:
  16. **
  17. **
  18. **
  19. ** GROUP DEFINITION GRAMMAR:
  20. **
  21. **    string = "sequence of alphanumeric characters"
  22. **    user_name ::= string
  23. **    group_name ::= string
  24. **    group_ref ::= group_name
  25. **    user_def ::= user_name | group_ref
  26. **    user_def_list ::= user_def { ',' user_def }
  27. **    user_part = user_def | '(' user_def_list ')'
  28. **
  29. **    templ = "sequence of alphanumeric characters and '*'s"
  30. **    ip_number_mask ::= templ '.' templ '.' templ '.' templ
  31. **    domain_name_mask ::= templ { '.' templ }
  32. **    address ::= ip_number_mask | domain_name_mask
  33. **    address_def ::= address
  34. **    address_def_list ::= address_def { ',' address_def }
  35. **    address_part = address_def | '(' address_def_list ')'
  36. **
  37. **    item ::= [user_part] ['@' address_part]
  38. **    item_list ::= item { ',' item }
  39. **    group_def ::= item_list
  40. **    group_decl ::= group_name ':' group_def
  41. **
  42. */
  43.  
  44.  
  45.  
  46. #include "HTUtils.h"
  47. #include <string.h>
  48. #include "HTAAUtil.h"
  49. #include "HTLex.h"    /* Lexical analysor    */
  50. #include "HTGroup.h"    /* Implemented here    */
  51.  
  52. #include "LYLeaks.h"
  53.  
  54. /*
  55. ** Group file parser
  56. */
  57.  
  58. typedef HTList UserDefList;
  59. typedef HTList AddressDefList;
  60.  
  61. typedef struct {
  62.     UserDefList *    user_def_list;
  63.     AddressDefList *    address_def_list;
  64. } Item;
  65.  
  66. typedef struct {
  67.     char *    name;
  68.     GroupDef *    translation;
  69. } Ref;
  70.  
  71.     
  72.  
  73. PRIVATE void syntax_error ARGS3(FILE *,     fp,
  74.                 char *,     msg,
  75.                 LexItem, lex_item)
  76. {
  77.     char buffer[41];
  78.     int cnt = 0;
  79.     char ch;
  80.  
  81.     while ((ch = getc(fp)) != EOF  &&  ch != '\n')
  82.     if (cnt < 40) buffer[cnt++] = ch;
  83.     buffer[cnt] = (char)0;
  84.  
  85.     if (TRACE)
  86.     fprintf(stderr, "%s %d before: '%s'\nHTGroup.c: %s (got %s)\n",
  87.         "HTGroup.c: Syntax error in rule file at line",
  88.         lex_line, buffer, msg, lex_verbose(lex_item));
  89.     lex_line++;
  90. }
  91.  
  92.  
  93. PRIVATE AddressDefList *parse_address_part ARGS1(FILE *, fp)
  94. {
  95.     AddressDefList *address_def_list = NULL;
  96.     LexItem lex_item;
  97.     BOOL only_one = NO;
  98.  
  99.     lex_item = lex(fp);
  100.     if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR)
  101.     only_one = YES;
  102.     else if (lex_item != LEX_OPEN_PAREN  ||
  103.          ((lex_item = lex(fp)) != LEX_ALPH_STR &&
  104.           lex_item != LEX_TMPL_STR)) {
  105.     syntax_error(fp, "Expecting a single address or '(' beginning list",
  106.              lex_item);
  107.     return NULL;
  108.     }
  109.     address_def_list = HTList_new();
  110.  
  111.     for(;;) {
  112.     Ref *ref = (Ref*)malloc(sizeof(Ref));
  113.     ref->name = NULL;
  114.     ref->translation = NULL;
  115.     StrAllocCopy(ref->name, lex_buffer);
  116.     
  117.     HTList_addObject(address_def_list, (void*)ref);
  118.  
  119.     if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
  120.         break;
  121.     /*
  122.     ** Here lex_item == LEX_ITEM_SEP; after item separator it
  123.     ** is ok to have one or more newlines (LEX_REC_SEP) and
  124.     ** they are ignored (continuation line).
  125.     */
  126.     do {
  127.         lex_item = lex(fp);
  128.     } while (lex_item == LEX_REC_SEP);
  129.  
  130.     if (lex_item != LEX_ALPH_STR && lex_item != LEX_TMPL_STR) {
  131.         syntax_error(fp, "Expecting an address template", lex_item);
  132.         HTList_delete(address_def_list);
  133.         return NULL;
  134.     }
  135.     }
  136.  
  137.     if (!only_one && lex_item != LEX_CLOSE_PAREN) {
  138.     HTList_delete(address_def_list);
  139.     syntax_error(fp, "Expecting ')' closing address list", lex_item);
  140.     return NULL;
  141.     }
  142.     return address_def_list;
  143. }
  144.  
  145.  
  146. PRIVATE UserDefList *parse_user_part ARGS1(FILE *, fp)
  147. {
  148.     UserDefList *user_def_list = NULL;
  149.     LexItem lex_item;
  150.     BOOL only_one = NO;
  151.  
  152.     lex_item = lex(fp);
  153.     if (lex_item == LEX_ALPH_STR)
  154.     only_one = YES;
  155.     else if (lex_item != LEX_OPEN_PAREN  ||
  156.          (lex_item = lex(fp)) != LEX_ALPH_STR) {
  157.     syntax_error(fp, "Expecting a single name or '(' beginning list",
  158.              lex_item);
  159.     return NULL;
  160.     }
  161.     user_def_list = HTList_new();
  162.  
  163.     for (;;) {
  164.     Ref *ref = (Ref*)malloc(sizeof(Ref));
  165.     ref->name = NULL;
  166.     ref->translation = NULL;
  167.     StrAllocCopy(ref->name, lex_buffer);
  168.  
  169.     HTList_addObject(user_def_list, (void*)ref);
  170.     
  171.     if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
  172.         break;
  173.     /*
  174.     ** Here lex_item == LEX_ITEM_SEP; after item separator it
  175.     ** is ok to have one or more newlines (LEX_REC_SEP) and
  176.     ** they are ignored (continuation line).
  177.     */
  178.     do {
  179.         lex_item = lex(fp);
  180.     } while (lex_item == LEX_REC_SEP);
  181.  
  182.     if (lex_item != LEX_ALPH_STR) {
  183.         syntax_error(fp, "Expecting user or group name", lex_item);
  184.         HTList_delete(user_def_list);
  185.         return NULL;
  186.     }
  187.     }
  188.  
  189.     if (!only_one && lex_item != LEX_CLOSE_PAREN) {
  190.     HTList_delete(user_def_list);
  191.     syntax_error(fp, "Expecting ')' closing user/group list", lex_item);
  192.     return NULL;
  193.     }
  194.     return user_def_list;
  195. }
  196.  
  197.  
  198. PRIVATE Item *parse_item ARGS1(FILE *, fp)
  199. {
  200.     Item *item = NULL;
  201.     UserDefList *user_def_list = NULL;
  202.     AddressDefList *address_def_list = NULL;
  203.     LexItem lex_item;
  204.  
  205.     lex_item = lex(fp);
  206.     if (lex_item == LEX_ALPH_STR || lex_item == LEX_OPEN_PAREN) {
  207.     unlex(lex_item);
  208.     user_def_list = parse_user_part(fp);
  209.     lex_item = lex(fp);
  210.     }
  211.  
  212.     if (lex_item == LEX_AT_SIGN) {
  213.     lex_item = lex(fp);
  214.     if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR ||
  215.         lex_item == LEX_OPEN_PAREN) {
  216.         unlex(lex_item);
  217.         address_def_list = parse_address_part(fp);
  218.     }
  219.     else {
  220.         if (user_def_list) HTList_delete(user_def_list);    /* @@@@ */
  221.         syntax_error(fp, "Expected address part (single address or list)",
  222.              lex_item);
  223.         return NULL;
  224.     }
  225.     }
  226.     else unlex(lex_item);
  227.  
  228.     if (!user_def_list && !address_def_list) {
  229.     syntax_error(fp, "Empty item not allowed", lex_item);
  230.     return NULL;
  231.     }
  232.     item = (Item*)malloc(sizeof(Item));
  233.     item->user_def_list = user_def_list;
  234.     item->address_def_list = address_def_list;
  235.     return item;
  236. }
  237.  
  238.  
  239. PRIVATE ItemList *parse_item_list ARGS1(FILE *, fp)
  240. {
  241.     ItemList *item_list = HTList_new();
  242.     Item *item;
  243.     LexItem lex_item;
  244.  
  245.     for(;;) {
  246.     if (!(item = parse_item(fp))) {
  247.         HTList_delete(item_list);    /* @@@@ */
  248.         return NULL;
  249.     }
  250.     HTList_addObject(item_list, (void*)item);
  251.     lex_item = lex(fp);
  252.     if (lex_item != LEX_ITEM_SEP) {
  253.         unlex(lex_item);
  254.         return item_list;
  255.     }
  256.     /*
  257.     ** Here lex_item == LEX_ITEM_SEP; after item separator it
  258.     ** is ok to have one or more newlines (LEX_REC_SEP) and
  259.     ** they are ignored (continuation line).
  260.     */
  261.     do {
  262.         lex_item = lex(fp);
  263.     } while (lex_item == LEX_REC_SEP);
  264.     unlex(lex_item);
  265.     }
  266. }
  267.  
  268.  
  269. PUBLIC GroupDef *HTAA_parseGroupDef ARGS1(FILE *, fp)
  270. {
  271.     ItemList *item_list = NULL;
  272.     GroupDef *group_def = NULL;
  273.     LexItem lex_item;
  274.  
  275.     if (!(item_list = parse_item_list(fp))) {
  276.     return NULL;
  277.     }
  278.     group_def = (GroupDef*)malloc(sizeof(GroupDef));
  279.     group_def->group_name = NULL;
  280.     group_def->item_list = item_list;
  281.  
  282.     if ((lex_item = lex(fp)) != LEX_REC_SEP) {
  283.     syntax_error(fp, "Garbage after group definition", lex_item);
  284.     }
  285.     
  286.     return group_def;
  287. }    
  288.  
  289.  
  290. PRIVATE GroupDef *parse_group_decl ARGS1(FILE *, fp)
  291. {
  292.     char *group_name = NULL;
  293.     GroupDef *group_def = NULL;
  294.     LexItem lex_item;
  295.  
  296.     do {
  297.     lex_item = lex(fp);
  298.     } while (lex_item == LEX_REC_SEP);    /* Ignore empty lines */
  299.  
  300.     if (lex_item != LEX_ALPH_STR) {
  301.     if (lex_item != LEX_EOF)
  302.         syntax_error(fp, "Expecting group name", lex_item);
  303.     return NULL;
  304.     }
  305.     StrAllocCopy(group_name, lex_buffer);
  306.  
  307.     if (LEX_FIELD_SEP != (lex_item = lex(fp))) {
  308.     syntax_error(fp, "Expecting field separator", lex_item);
  309.     free(group_name);
  310.     return NULL;
  311.     }
  312.  
  313.     if (!(group_def = HTAA_parseGroupDef(fp))) {
  314.     free(group_name);
  315.     return NULL;
  316.     }
  317.     group_def->group_name = group_name;
  318.  
  319.     return group_def;
  320. }
  321.     
  322.  
  323.  
  324. /*
  325. ** Group manipulation routines
  326. */
  327.  
  328. PRIVATE GroupDef *find_group_def ARGS2(GroupDefList *,    group_list,
  329.                        CONST char *,    group_name)
  330. {
  331.     if (group_list && group_name) {
  332.     GroupDefList *cur = group_list;
  333.     GroupDef *group_def;
  334.  
  335.     while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur))) {
  336.         if (!strcmp(group_name, group_def->group_name)) {
  337.         return group_def;
  338.             }
  339.         }
  340.     }
  341.     return NULL;
  342. }
  343.  
  344.  
  345. PUBLIC void HTAA_resolveGroupReferences ARGS2(GroupDef *,    group_def,
  346.                           GroupDefList *,    group_def_list)
  347. {
  348.     if (group_def && group_def->item_list && group_def_list) {
  349.     ItemList *cur1 = group_def->item_list;
  350.     Item *item;
  351.  
  352.     while (NULL != (item = (Item*)HTList_nextObject(cur1))) {
  353.         UserDefList *cur2 = item->user_def_list;
  354.         Ref *ref;
  355.  
  356.         while (NULL != (ref = (Ref*)HTList_nextObject(cur2)))
  357.         ref->translation = find_group_def(group_def_list, ref->name);
  358.  
  359.         /* Does NOT translate address_def_list */
  360.     }
  361.     }
  362. }
  363.  
  364.  
  365. PRIVATE void add_group_def ARGS2(GroupDefList *, group_def_list,
  366.                  GroupDef *,     group_def)
  367. {
  368.     HTAA_resolveGroupReferences(group_def, group_def_list);
  369.     HTList_addObject(group_def_list, (void*)group_def);
  370. }
  371.  
  372.  
  373. PRIVATE GroupDefList *parse_group_file ARGS1(FILE *, fp)
  374. {
  375.     GroupDefList *group_def_list = HTList_new();
  376.     GroupDef *group_def;
  377.     
  378.     while (NULL != (group_def = parse_group_decl(fp)))
  379.     add_group_def(group_def_list, group_def);
  380.     
  381.     return group_def_list;
  382. }
  383.  
  384.  
  385. /*
  386. ** Trace functions
  387. */
  388.  
  389. PRIVATE void print_item ARGS1(Item *, item)
  390. {
  391.     if (!item)
  392.     fprintf(stderr, "\tNULL-ITEM\n");
  393.     else {
  394.     UserDefList *cur1 = item->user_def_list;
  395.     AddressDefList *cur2 = item->address_def_list;
  396.     Ref *user_ref = (Ref*)HTList_nextObject(cur1);
  397.     Ref *addr_ref = (Ref*)HTList_nextObject(cur2);
  398.  
  399.     if (user_ref) {
  400.         fprintf(stderr, "\t[%s%s", user_ref->name,
  401.             (user_ref->translation ? "*REF*" : ""));
  402.         while (NULL != (user_ref = (Ref*)HTList_nextObject(cur1)))
  403.         fprintf(stderr, "; %s%s", user_ref->name,
  404.             (user_ref->translation ? "*REF*" : ""));
  405.         fprintf(stderr, "] ");
  406.     } else fprintf(stderr, "\tANYBODY ");
  407.  
  408.     if (addr_ref) {
  409.         fprintf(stderr, "@ [%s", addr_ref->name);
  410.         while (NULL != (addr_ref = (Ref*)HTList_nextObject(cur2)))
  411.         fprintf(stderr, "; %s", addr_ref->name);
  412.         fprintf(stderr, "]\n");
  413.     } else fprintf(stderr, "@ ANYADDRESS\n");
  414.     }
  415. }
  416.  
  417.  
  418. PRIVATE void print_item_list ARGS1(ItemList *, item_list)
  419. {
  420.     ItemList *cur = item_list;
  421.     Item *item;
  422.  
  423.     if (!item_list)
  424.     fprintf(stderr, "EMPTY");
  425.     else while (NULL != (item = (Item*)HTList_nextObject(cur)))
  426.     print_item(item);
  427. }
  428.  
  429.  
  430. PUBLIC void HTAA_printGroupDef ARGS1(GroupDef *, group_def)
  431. {
  432.     if (!group_def) {
  433.     fprintf(stderr, "\nNULL RECORD\n");
  434.     return;
  435.     }
  436.  
  437.     fprintf(stderr, "\nGroup %s:\n",
  438.         (group_def->group_name ? group_def->group_name : "NULL"));
  439.  
  440.     print_item_list(group_def->item_list);
  441.     fprintf(stderr, "\n");
  442. }
  443.  
  444.  
  445. PRIVATE void print_group_def_list ARGS1(GroupDefList *, group_list)
  446. {
  447.     GroupDefList *cur = group_list;
  448.     GroupDef *group_def;
  449.     
  450.     while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur)))
  451.     HTAA_printGroupDef(group_def);
  452. }
  453.  
  454.  
  455.  
  456. /*
  457. ** IP address template matching
  458. */
  459.  
  460. /* PRIVATE                        part_match()
  461. **        MATCH ONE PART OF INET ADDRESS AGAIST
  462. **        A PART OF MASK (inet address has 4 parts)
  463. ** ON ENTRY:
  464. **    tcur    pointer to the beginning of template part.
  465. **    icur    pointer to the beginning of actual inet
  466. **        number part.
  467. **
  468. ** ON EXIT:
  469. **    returns    YES, if match.
  470. */
  471. PRIVATE BOOL part_match ARGS2(CONST char *, tcur,
  472.                   CONST char *, icur)
  473. {
  474.     char required[4];
  475.     char actual[4];
  476.     CONST char *cur;
  477.     int cnt;
  478.  
  479.     if (!tcur || !icur) return NO;
  480.  
  481.     cur=tcur;
  482.     cnt=0;
  483.     while (cnt < 3  &&  *cur && *cur != '.')
  484.     required[cnt++] = *(cur++);
  485.     required[cnt] = (char)0;
  486.  
  487.     cur=icur;
  488.     cnt=0;
  489.     while (cnt < 3  &&  *cur && *cur != '.')
  490.     actual[cnt++] = *(cur++);
  491.     actual[cnt] = (char)0;
  492.  
  493.     if (TRACE) {
  494.     BOOL status = HTAA_templateMatch(required, actual);
  495.     fprintf(stderr, "part_match: req: '%s' act: '%s' match: %s\n",
  496.         required, actual, (status ? "yes" : "no"));
  497.     return status;
  498.     }
  499.  
  500.     return HTAA_templateMatch(required, actual);
  501. }
  502.  
  503.  
  504.  
  505. /* PRIVATE                        ip_number_match()
  506. **        MATCH INET NUMBER AGAINST AN INET NUMBER MASK
  507. ** ON ENTRY:
  508. **    template    mask to match agaist, e.g. 128.141.*.*
  509. **    inet_addr    actual inet address, e.g. 128.141.201.74
  510. **
  511. ** ON EXIT:
  512. **    returns        YES, if match;  NO, if not.
  513. */
  514. PRIVATE BOOL ip_number_match ARGS2(CONST char *,    template,
  515.                    CONST char *,    inet_addr)
  516. {
  517.     CONST char *tcur = template;
  518.     CONST char *icur = inet_addr;
  519.     int cnt;
  520.     
  521.     for (cnt=0; cnt<4; cnt++) {
  522.     if (!tcur || !icur || !part_match(tcur, icur))
  523.         return NO;
  524.     if (NULL != (tcur = strchr(tcur, '.'))) tcur++;
  525.     if (NULL != (icur = strchr(icur, '.'))) icur++;
  526.     }
  527.     return YES;
  528. }
  529.  
  530.  
  531.  
  532. /* PRIVATE                        is_domain_mask()
  533. **        DETERMINE IF A GIVEN MASK IS A
  534. **        DOMAIN NAME MASK OR AN INET NUMBER MASK
  535. ** ON ENTRY:
  536. **    mask    either a domain name mask,
  537. **        e.g.
  538. **            *.cern.ch
  539. **
  540. **        or an inet number mask,
  541. **        e.g.
  542. **            128.141.*.*
  543. **
  544. ** ON EXIT:
  545. **    returns    YES, if mask is a domain name mask.
  546. **        NO, if it is an inet number mask.
  547. */
  548. PRIVATE BOOL is_domain_mask ARGS1(CONST char *,    mask)
  549. {
  550.     CONST char *cur = mask;
  551.  
  552.     if (!mask) return NO;
  553.  
  554.     while (*cur) {
  555.     if (*cur != '.'  &&  *cur != '*'  &&  (*cur < '0' || *cur > '9'))
  556.         return YES;    /* Even one non-digit makes it a domain name mask */
  557.     cur++;
  558.     }
  559.     return NO;    /* All digits and dots, so it is an inet number mask */
  560. }
  561.  
  562.  
  563.  
  564. /* PRIVATE                            ip_mask_match()
  565. **        MATCH AN IP NUMBER MASK OR IP NAME MASK
  566. **        AGAINST ACTUAL IP NUMBER OR IP NAME
  567. **        
  568. ** ON ENTRY:
  569. **    mask        mask. Mask may be either an inet number
  570. **            mask or a domain name mask,
  571. **            e.g.
  572. **                128.141.*.*
  573. **            or
  574. **                *.cern.ch
  575. **
  576. **    ip_number    IP number of connecting host.
  577. **    ip_name        IP name of the connecting host.
  578. **
  579. ** ON EXIT:
  580. **    returns        YES, if hostname/internet number
  581. **            matches the mask.
  582. **            NO, if no match (no fire).
  583. */
  584. PRIVATE BOOL ip_mask_match ARGS3(CONST char *,    mask,
  585.                  CONST char *,    ip_number,
  586.                  CONST char *,    ip_name)
  587. {
  588.     if (mask && (ip_number || ip_name)) {
  589.     if (is_domain_mask(mask)) {
  590.         if (HTAA_templateMatch(mask, ip_name))
  591.         return YES;
  592.     }
  593.     else {
  594.         if (ip_number_match(mask, ip_number))
  595.         return YES;
  596.     }
  597.     }
  598.     return NO;
  599. }
  600.  
  601.  
  602.  
  603.  
  604. PRIVATE BOOL ip_in_def_list ARGS3(AddressDefList *,    address_def_list,
  605.                   char *,        ip_number,
  606.                   char *,        ip_name)
  607. {
  608.     if (address_def_list && (ip_number || ip_name)) {
  609.     AddressDefList *cur = address_def_list;
  610.     Ref *ref;
  611.  
  612.     while (NULL != (ref = (Ref*)HTList_nextObject(cur))) {
  613.         /* Value of ref->translation is ignored, i.e. */
  614.         /* no recursion for ip address tamplates.      */
  615.         if (ip_mask_match(ref->name, ip_number, ip_name))
  616.         return YES;
  617.     }
  618.     }
  619.     return NO;
  620. }
  621.  
  622.  
  623. /*
  624. ** Group file cached reading
  625. */
  626.  
  627. typedef struct {
  628.     char *       group_filename;
  629.     GroupDefList * group_list;
  630. } GroupCache;
  631.  
  632. typedef HTList GroupCacheList;
  633.  
  634. PRIVATE GroupCacheList *group_cache_list = NULL;
  635.  
  636.  
  637. PUBLIC GroupDefList *HTAA_readGroupFile ARGS1(CONST char *, filename)
  638. {
  639.     FILE *fp;
  640.     GroupCache *group_cache;
  641.  
  642.     if (!filename || !*filename) return NULL;
  643.  
  644.     if (!group_cache_list)
  645.     group_cache_list = HTList_new();
  646.     else {
  647.     GroupCacheList *cur = group_cache_list;
  648.  
  649.     while (NULL != (group_cache = (GroupCache*)HTList_nextObject(cur))) {
  650.         if (!strcmp(filename, group_cache->group_filename)) {
  651.         if (TRACE) fprintf(stderr, "%s '%s' %s\n",
  652.                    "HTAA_readGroupFile: group file",
  653.                    filename, "already found in cache");
  654.         return group_cache->group_list;
  655.         } /* if cache match */
  656.     } /* while cached files remain */
  657.     } /* cache exists */
  658.  
  659.     if (TRACE) fprintf(stderr, "HTAA_readGroupFile: reading group file `%s'\n",
  660.                filename);
  661.  
  662.     if (!(fp = fopen(filename, "r"))) {
  663.     if (TRACE) fprintf(stderr, "%s '%s'\n",
  664.                "HTAA_readGroupFile: unable to open group file",
  665.                filename);
  666.     return NULL;
  667.     }
  668.  
  669.     if (!(group_cache = (GroupCache*)malloc(sizeof(GroupCache))))
  670.     outofmem(__FILE__, "HTAA_readGroupFile");
  671.  
  672.     group_cache->group_filename = NULL;
  673.     StrAllocCopy(group_cache->group_filename, filename);
  674.     group_cache->group_list = parse_group_file(fp);
  675.     HTList_addObject(group_cache_list, (void*)group_cache);
  676.     fclose(fp);
  677.  
  678.     if (TRACE) {
  679.     fprintf(stderr, "Read group file '%s', results follow:\n", filename);
  680.     print_group_def_list(group_cache->group_list);
  681.     }
  682.  
  683.     return group_cache->group_list;
  684. }
  685.  
  686.  
  687. /* PUBLIC                    HTAA_userAndInetInGroup()
  688. **        CHECK IF USER BELONGS TO TO A GIVEN GROUP
  689. **        AND THAT THE CONNECTION COMES FROM AN
  690. **        ADDRESS THAT IS ALLOWED BY THAT GROUP
  691. ** ON ENTRY:
  692. **    group        the group definition structure.
  693. **    username    connecting user.
  694. **    ip_number    browser host IP number, optional.
  695. **    ip_name        browser host IP name, optional.
  696. **            However, one of ip_number or ip_name
  697. **            must be given.
  698. ** ON EXIT:
  699. **    returns        HTAA_IP_MASK, if IP address mask was
  700. **            reason for failing.
  701. **            HTAA_NOT_MEMBER, if user does not belong
  702. **            to the group.
  703. **            HTAA_OK if both IP address and user are ok.
  704. */
  705. PUBLIC HTAAFailReasonType HTAA_userAndInetInGroup ARGS4(GroupDef *, group,
  706.                             char *,        username,
  707.                             char *,        ip_number,
  708.                             char *,        ip_name)
  709. {
  710.     HTAAFailReasonType reason = HTAA_NOT_MEMBER;
  711.  
  712.     if (group && username) {
  713.     ItemList *cur1 = group->item_list;
  714.     Item *item;
  715.  
  716.     while (NULL != (item = (Item*)HTList_nextObject(cur1))) {
  717.         if (!item->address_def_list ||    /* Any address allowed */
  718.         ip_in_def_list(item->address_def_list, ip_number, ip_name)) {
  719.             
  720.         if (!item->user_def_list)    /* Any user allowed */
  721.             return HTAA_OK;
  722.         else {
  723.             UserDefList *cur2 = item->user_def_list;
  724.             Ref *ref;
  725.  
  726.             while (NULL != (ref = (Ref*)HTList_nextObject(cur2))) {
  727.             
  728.             if (ref->translation) {    /* Group, check recursively */
  729.                 reason = HTAA_userAndInetInGroup(ref->translation,
  730.                                  username,
  731.                                  ip_number,ip_name);
  732.                 if (reason == HTAA_OK)
  733.                 return HTAA_OK;
  734.             }
  735.             else {    /* Username, check directly */
  736.                 if (username && *username &&
  737.                 0==strcmp(ref->name, username))
  738.                 return HTAA_OK;
  739.             }
  740.             } /* Every user/group name in this group */
  741.         } /* search for username */
  742.         } /* IP address ok */
  743.         else {
  744.         reason = HTAA_IP_MASK;
  745.         }
  746.     } /* while items in group */
  747.     } /* valid parameters */
  748.     
  749.     return reason;        /* No match, or invalid parameters */
  750. }
  751.  
  752.  
  753. PUBLIC void GroupDef_delete ARGS1(GroupDef *, group_def)
  754. {
  755.     if (group_def) {
  756.     FREE(group_def->group_name);
  757.     if (group_def->item_list)
  758.         HTList_delete(group_def->item_list);    /* @@@@ */
  759.     free(group_def);
  760.     }
  761. }
  762.  
  763.